#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "functions.h"
#define BUFLEN 256

int main(int argc, char** argv)
{
    FILE* output;
    int serverSocketTCP, numBytesRecived, it_socket;
    int auth = 0, tmp_nc, tr = 0;
    double tmp_s;
    struct sockaddr_in serverSocketAddrTCP;
    fd_set read_fds, tmp_fds;
    char buffer[BUFLEN], command[BUFLEN], filename[20];
    if (argc != 3)
        clientUsage();

    sprintf(filename, "client-%d.log", getpid());

    //Deschidere fisier output.
    output = fopen(filename, "w");

    //Deschidere socket.
    serverSocketTCP = socket(PF_INET, SOCK_STREAM, 0);
    //Configurare socket.
    serverSocketAddrTCP.sin_family = AF_INET;
    serverSocketAddrTCP.sin_port = htons(atoi(argv[2]));
    inet_aton(argv[1], &serverSocketAddrTCP.sin_addr);

    //Connectare la server.
    if ((connect(serverSocketTCP, ((struct sockaddr*)&serverSocketAddrTCP),
                 sizeof(struct sockaddr))) != 0) {
        fprintf(output, "-10 : Eroare apel connect \n");
    }

    //Adaugare stdin in multimea descriptorilor de citire.
    FD_SET(0, &read_fds);

    //Adaugare socket server in multimea descriptorilor de citire.
    FD_SET(serverSocketTCP, &read_fds);
    while (1) {
        tmp_fds = read_fds;
        if (select(serverSocketTCP + 1, &tmp_fds, NULL, NULL, NULL) == -1) {
            fprintf(output, "-10 : Eroare apel select \n");
        }

        for (it_socket = 0; it_socket <= serverSocketTCP; it_socket++) {
            if (FD_ISSET(it_socket, &tmp_fds)) {
                if (it_socket == serverSocketTCP) {
                    numBytesRecived = recv(serverSocketTCP, &buffer, BUFLEN, 0);
                    if (numBytesRecived <= 0) {
                        if (numBytesRecived < 0) {
                            fprintf(output, "-10 : Eroare apel recv \n");
                        }
                        fclose(output);
                        close(it_socket);
                        FD_CLR(it_socket, &read_fds);
                        return 0;
                    } else {
                        //Am primit mesaj din partea server-ului.
                        fprintf(output, "IBANK> %s", buffer);
                        sscanf(buffer, "%s", command);
                        if (strcmp(command, "Welcome") == 0) {
                            auth = 1;
                            break;
                        }
                    }
                } else if (it_socket == 0) {
                    //Input pentru comanda ce va fi trimisa catre server.
                    fgets(buffer, BUFLEN, stdin);
                    fprintf(output, "%s", buffer);
                    sscanf(buffer, "%s", command);
                    if (strcmp(command, "login") == 0) {
                        if (auth == 1) {
                            //Nu mai trimit comanda la server.
                            fprintf(output, "IBANK> -2 : Sesiune deja deschisa\n");
                            break;
                        } else {
                            send(serverSocketTCP, buffer, strlen(buffer) + 1, 0);
                            break;
                        }
                    } else {
                        if (strcmp(command, "quit") == 0) {
                            send(serverSocketTCP, buffer, strlen(buffer) + 1, 0);
                            FD_CLR(serverSocketTCP, &read_fds);
                            close(serverSocketTCP);
                            fclose(output);
                            return 0;
                        }
                        if (auth == 0) {
                            fprintf(output, "IBANK> -1 : Clientul nu este autentificat \n");
                        } else {
                            if (strcmp(command, "logout") == 0) {
                                if (auth == 0) {
                                    fprintf(output, "-1 : Clientul nu este autentificat \n");
                                } else {
                                    auth = 0;
                                    send(serverSocketTCP, buffer, strlen(buffer) + 1, 0);
                                    break;
                                }
                            }
                            if (strcmp(command, "listsold") == 0) {
                                send(serverSocketTCP, buffer, strlen(buffer) + 1, 0);
                                break;
                            }
                            if (strcmp(command, "transfer") == 0) {
                                sscanf(buffer, "%s %d %lf", &command, &tmp_nc, &tmp_s);
                                tr = 1;
                                send(serverSocketTCP, buffer, strlen(buffer) + 1, 0);
                                break;
                            }
                            if (tr == 1) {
                                if (command[0] == 'y') {
                                    sprintf(buffer, "transfer2 %d %.2f", tmp_nc, tmp_s);
                                    send(serverSocketTCP, buffer, strlen(buffer) + 1, 0);
                                    tr = 0;
                                    break;
                                } else {
                                    sprintf(buffer, "transfer2 0 0");
                                    send(serverSocketTCP, buffer, strlen(buffer) + 1, 0);
                                    tr = 0;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return 0;
}
